#include "characterclassesform.h"
#include "ui_characterclassesform.h"


#include <characterclass.h>
#include <classlevel.h>


#include <QMetaType>
#include <QTreeView>
#include <QMenu>
#include <QDebug>
#include <QInputDialog>
#include <QTimer>
#include <QMessageBox>


CharacterClassesForm::CharacterClassesForm(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::CharacterClassesForm)
{
    m_model = new CharacterClassModel(this);

    connect(m_model, &QIdentityProxyModel::modelAboutToBeReset, this, &CharacterClassesForm::onModelAboutToBeReset);
    connect(m_model, &QIdentityProxyModel::modelReset, this, &CharacterClassesForm::onModelReset);

    ui->setupUi(this);

    m_splitter = 0;
    m_mainTabs = 0;

}

CharacterClassesForm::~CharacterClassesForm()
{
    delete ui;
}

void CharacterClassesForm::setModel(DTwentyModel *model)
{
    m_model->setSourceModel(model);
}

void CharacterClassesForm::addCharacterClass()
{
    QModelIndex characterClassesIndex = characterClassContainerIndex();

    if (!characterClassesIndex.isValid())
    {
        return;
    }

    int rows = m_model->rowCount(characterClassesIndex);
    if (!m_model->insertRows(rows, 1, characterClassesIndex))
    {
        return;
    }

    QModelIndex characterClassIndex = m_model->index(rows, 0, characterClassesIndex);
    if (!characterClassIndex.isValid())
    {
        return;
    }

    m_model->setData(characterClassIndex, tr("New Character Class"));

    int tabIndex = createCharacterClassTab(characterClassIndex);
    if (tabIndex < 0)
    {
        return;
    }

    onRenameTab(tabIndex, m_mainTabs);
    m_mainTabs->setCurrentIndex(tabIndex);

    QTimer::singleShot(0, this, SLOT(onCharacterClassAdded()));

}

void CharacterClassesForm::onModelAboutToBeReset()
{
    if (m_splitter)
    {
        m_splitter->hide();
        m_splitter->setParent(0);
        m_splitter->deleteLater();
    }

    m_splitter = new QSplitter(this);
    layout()->addWidget(m_splitter);

    m_mainTabs = new QTabWidget(this);
    m_splitter->addWidget(m_mainTabs);
    connect(m_mainTabs, &QTabWidget::currentChanged, this, &CharacterClassesForm::onCurrentTabChanged);

    QTabBar* tabBar = m_mainTabs->tabBar();
    tabBar->setContextMenuPolicy(Qt::CustomContextMenu);
    connect(tabBar, &QTabBar::customContextMenuRequested, this, &CharacterClassesForm::onCustomContextMenuRequested);
}

void CharacterClassesForm::onModelReset()
{
    if (!m_splitter || !m_mainTabs)
    {
        return;
    }

    QModelIndex characterClassesIndex = characterClassContainerIndex();

    if (!characterClassesIndex.isValid())
    {
        return;
    }

    QModelIndex characterClassIndex = characterClassesIndex.child(0,0);
    while (characterClassIndex.isValid())
    {
        createCharacterClassTab(characterClassIndex);

        characterClassIndex = characterClassIndex.sibling(characterClassIndex.row()+1, characterClassIndex.column());
    }
}

void CharacterClassesForm::onCurrentTabChanged(int index)
{
    Q_UNUSED(index);
    QTabWidget* tabWidget = qobject_cast<QTabWidget*>(sender());
    if (!tabWidget)
    {
        return;
    }

    QTreeView* treeView = qobject_cast<QTreeView*>(tabWidget->currentWidget());
    if (!treeView)
    {
        return;
    }

    QModelIndex expandIndex = treeView->rootIndex().child(0,0);
    while (expandIndex.isValid())
    {
        treeView->expand(expandIndex);
        expandIndex = expandIndex.sibling(expandIndex.row()+1, expandIndex.column());
    }

}

void CharacterClassesForm::onTabCloseRequested(int index)
{
    QTabWidget* tabWidgetFrom = qobject_cast<QTabWidget*>(sender());
    if (tabWidgetFrom == m_mainTabs)
    {
        return;
    }

    onMoveTab(index, tabWidgetFrom, m_mainTabs);
}

void CharacterClassesForm::onCustomContextMenuRequested(const QPoint &pos)
{
    qDebug() << Q_FUNC_INFO;

    QTabBar* tabBar = qobject_cast<QTabBar*>(sender());
    if (!tabBar)
    {
        qDebug() << Q_FUNC_INFO << "Not a tab bar";
        return;
    }

    QTabWidget* tabWidgetFrom = qobject_cast<QTabWidget*>(tabBar->parent());
    if (!tabWidgetFrom)
    {
        qDebug() << Q_FUNC_INFO << "Not a tab widget";
        return;
    }

    int index = tabBar->tabAt(pos);
    if (index < 0)
    {
        qDebug() << Q_FUNC_INFO << "Invalid tab index";
        return;
    }

    if (tabWidgetFrom == m_mainTabs && tabWidgetFrom->count() <= 1)
    {
        return;
    }

    QMenu menu;

    QAction* actRename = menu.addAction(tr("Rename"));
    menu.addSeparator();

    QAction* actSplit = 0;
    if (tabWidgetFrom->count() > 1)
    {
        actSplit = menu.addAction(tr("Split"));
    }

    if (m_splitter->count() > 1)
    {
        QMenu* sub = menu.addMenu(tr("Move"));
        for (int i = 0; i < m_splitter->count(); i++)
        {
            QTabWidget* w = qobject_cast<QTabWidget*>(m_splitter->widget(i));
            if (w == tabWidgetFrom)
            {
                continue;
            }

            QAction* act = sub->addAction(tr("%1").arg(i+1));
            act->setData(i);
        }
    }

    menu.addSeparator();
    QAction* actRemove = menu.addAction(tr("Remove"));

    QAction* act = menu.exec(QCursor::pos());
    if (!act)
    {
        return;
    }

    if (act == actRename)
    {
        onRenameTab(index, tabWidgetFrom);
        return;
    }

    if (act == actSplit)
    {
        onSplitTab(index, tabWidgetFrom);
        return;
    }

    if (act == actRemove)
    {
        onRemoveTab(index, tabWidgetFrom);
        return;
    }

    QTabWidget* targetTabWidget = qobject_cast<QTabWidget*>(m_splitter->widget(act->data().toInt()));
    onMoveTab(index, tabWidgetFrom, targetTabWidget);


}

void CharacterClassesForm::onRenameTab(int index, QTabWidget *tabWidgetFrom)
{
    QTreeView* view = qobject_cast<QTreeView*>(tabWidgetFrom->widget(index));
    if (!view)
    {
        return;
    }

    QString text = tabWidgetFrom->tabText(index);
    text = QInputDialog::getText(this, tr("Rename"), tr("Enter new name"), QLineEdit::Normal, text);

    if (text.isEmpty())
    {
        return;
    }

    if (!view->model()->setData(view->rootIndex(), text))
    {
        qDebug() << Q_FUNC_INFO << "Failed to rename character class!";
        return;
    }

    tabWidgetFrom->setTabText(index, text);

}

void CharacterClassesForm::onSplitTab(int index, QTabWidget *tabWidgetFrom)
{
    if (!m_splitter)
    {
        return;
    }

    QTabWidget* tabWidgdetTo = new QTabWidget(this);
    tabWidgdetTo->setTabsClosable(true);
    connect(tabWidgdetTo, &QTabWidget::currentChanged, this, &CharacterClassesForm::onCurrentTabChanged);
    connect(tabWidgdetTo, &QTabWidget::tabCloseRequested, this, &CharacterClassesForm::onTabCloseRequested);

    QTabBar* tabBar = tabWidgdetTo->tabBar();
    tabBar->setContextMenuPolicy(Qt::CustomContextMenu);
    connect(tabBar, &QTabBar::customContextMenuRequested, this, &CharacterClassesForm::onCustomContextMenuRequested);

    onMoveTab(index, tabWidgetFrom, tabWidgdetTo);

    m_splitter->addWidget(tabWidgdetTo);

}

void CharacterClassesForm::onMoveTab(int index, QTabWidget *tabWidgetFrom, QTabWidget *tabWidgetTo)
{
    if (!tabWidgetFrom || !tabWidgetTo)
    {
        return;
    }

    QWidget* widget = tabWidgetFrom->widget(index);
    if (!widget)
    {
        return;
    }

    QString text = tabWidgetFrom->tabText(index);
    tabWidgetFrom->removeTab(index);
    tabWidgetTo->addTab(widget, text);

    if (tabWidgetFrom == m_mainTabs && tabWidgetFrom->count() > 0)
    {
        return;
    }

    tabWidgetFrom->deleteLater();
}

void CharacterClassesForm::onRemoveTab(int index, QTabWidget *tabWidgetFrom)
{
    QString text = tabWidgetFrom->tabText(index);
    if (QMessageBox::question(this, tr("Remove %1?").arg(text), tr("Do you want to remove\n%1 character class?").arg(text), QMessageBox::Yes | QMessageBox::No)
            != QMessageBox::Yes)
    {
        return;
    }

    QTreeView* view = qobject_cast<QTreeView*>(tabWidgetFrom->widget(index));
    if (!view)
    {
        return;
    }

    QModelIndex modelIndex = view->rootIndex();
    if (!m_model->removeRows(modelIndex.row(), 0, modelIndex.parent()))
    {
        return;
    }

    tabWidgetFrom->removeTab(index);
    view->deleteLater();

    if (tabWidgetFrom == m_mainTabs || tabWidgetFrom->count() > 0)
    {
        return;
    }

    tabWidgetFrom->deleteLater();
}

void CharacterClassesForm::onCharacterClassAdded()
{
    QTreeView* view = qobject_cast<QTreeView*>(m_mainTabs->currentWidget());
    if (!view)
    {
        return;
    }

    int classLevelsTypeId = qMetaTypeId<ClassLevels*>();

    QModelIndex modelIndex = view->rootIndex().child(0,0);
    while (modelIndex.isValid())
    {
        if (modelIndex.data(DTwentyModel::Role_TYPE).toInt() == classLevelsTypeId)
        {
            m_model->insertRows(0, 20, modelIndex);
            break;
        }

        modelIndex = modelIndex.sibling(modelIndex.row()+1, modelIndex.column());
    }
}


int CharacterClassesForm::createCharacterClassTab(const QModelIndex &modelIndex)
{
    if (!m_mainTabs)
    {
        return -1;
    }

    foreach (const QTreeView* view, findChildren<const QTreeView*>(QString(), Qt::FindDirectChildrenOnly))
    {
        if (view->rootIndex().data().toString().toLower() == modelIndex.data().toString().toLower())
        {
            qDebug() << Q_FUNC_INFO << "Character class already has tab:" << modelIndex.data().toString();
            return -1;
        }
    }

    QTreeView* treeView = new QTreeView(this);
    treeView->setModel(m_model);
    treeView->setRootIndex(modelIndex);
    treeView->hideColumn(1);
    treeView->setAlternatingRowColors(true);

    return m_mainTabs->addTab(treeView, modelIndex.data().toString());
}

QModelIndex CharacterClassesForm::characterClassContainerIndex() const
{
    return m_model->characterClassContainerIndex();
//    int classesContainerType = qMetaTypeId<CharacterClasses*>();
//    QModelIndex topLevelIndex = m_model->index(0, 0);

//    while (topLevelIndex.isValid())
//    {
//        if (topLevelIndex.data(DTwentyModel::Role_TYPE) == classesContainerType)
//        {
//            return topLevelIndex;
//            break;
//        }

//        topLevelIndex = topLevelIndex.sibling(topLevelIndex.row()+1, topLevelIndex.column());
//    }

//    return QModelIndex();
}


